#include <string.h>

#include "lib.h"
#include "msgcompl.h"
#include "msgoutlt.h"
#include "msgplug.h"

MsgCompiled::MsgCompiled(MsgOutlets* outlets,
	char* src, int32 srclen
#ifdef USE_MSGGENCACHE	// not thread-safe
	, uint8 srcMD4[16]
#endif
	)
{
#ifdef USE_MSGGENCACHE	// not thread-safe
	memcpy(msgMD4, srcMD4, 16);
#endif

	pos = (MsgOutletPos*)0;

	if (src && srclen > 0)
	{
		char *start, *end, *oStart, *oEnd;
		int32 outletIndex;
		MsgOutletPos *newPos, *prev;

		prev = (MsgOutletPos*)0;
		start = src;
		end = start + srclen;

		while (start < end)
		{
			oStart = (char*)memchr(start, '<', end - start);
			if (oStart)
			{
				++start;

				oEnd = (char*)memchr(oStart + 1, '>', end - (oStart + 1));
				if (oEnd)
				{
					if (oEnd - oStart + 1 <= outlets->getMaxLen())
					{
						outletIndex = outlets->find(oStart, oEnd - oStart + 1);

						if (outletIndex != -1)
						{
							newPos = new MsgOutletPos(
								outletIndex,
								oStart - src);
							if (newPos)
							{
								if (prev)
									prev->next = newPos;
								else
									pos = newPos;
									
								prev = newPos;
							}
							start = oEnd + 1;
						}
					}
				}
				else
					break;
			}
			else
				break;
		}
	}
}

MsgCompiled::~MsgCompiled()
{
	MsgOutletPos* temp;

	while (pos)
	{
		temp = pos;
		pos = temp->next;
		delete temp;
	}
}

int32
MsgCompiled::getAllocLen(int32 srclen, MsgOutlets* outlets, MsgPlugs* plugs)
{
	int32 result;
	MsgOutletPos* probe;

	result = srclen + 1;		// term null included

	probe = pos;
	while (probe)
	{
		result -= outlets->getLen(probe->getOutletIndex());
		result += plugs->getLen(outlets->getId(probe->getOutletIndex()));

		probe = probe->next;
	}

	return result;
}
